package com.word.web.model;

import java.util.LinkedHashMap;

/**
 * 响应数据对象封装
 *
 * @author Sinlon 2021-06-22
 **/
public class Response extends LinkedHashMap<String, Object> {
    private static final long serialVersionUID = 1L;
    /**
     * HTTP状态码
     */
    private int httpcode;
    /**
     * HTTP错误消息
     */
    private String httperror;
    /**
     * 响应结果码
     */
    private int resultcode;
    /**
     * 响应错误消息
     */
    private String resulterror;
    /**
     * 业务提示消息
     */
    private String message;
    /**
     * 响应成功(Response Success)
     */
    private boolean rs;

    /**
     * 默认构造函数
     */
    public Response() {
    }

    /**
     * 带参数构造函数
     *
     * @param rs      业务处理成功
     * @param message 业务提示消息
     */
    public Response(boolean rs, String message) {
        Httpcode httpcode = rs ? Httpcode.SUCCESS : Httpcode.RESPONSE_FAIL;
        Resultcode resultcode = rs ? Resultcode.RESPONSE_SUCCESS : Resultcode.FAIL;
        this.rs = rs;
        this.message = message;
        this.resultcode = resultcode.getCode();
        this.resulterror = resultcode.getError();
        this.httpcode = httpcode.getCode();
        this.httperror = httpcode.getError();
        this.put("rs", rs);
        this.put("message", message);
        this.put("resultcode", resultcode.code());
        this.put("resulterror", resultcode.error());
        this.put("httpcode", httpcode.code());
        this.put("httperror", httpcode.error());
    }

    /**
     * 带参数构造函数
     *
     * @param rs       业务处理成功
     * @param message  业务提示消息
     * @param httpcode HTTP状态码
     */
    public Response(boolean rs, String message, Httpcode httpcode) {
        Resultcode resultcode = rs ? Resultcode.RESPONSE_SUCCESS : Resultcode.FAIL;
        this.rs = rs;
        this.message = message;
        this.resultcode = resultcode.getCode();
        this.resulterror = resultcode.getError();
        this.httpcode = httpcode.getCode();
        this.httperror = httpcode.getError();
        this.put("rs", rs);
        this.put("message", message);
        this.put("resultcode", resultcode.code());
        this.put("resulterror", resultcode.error());
        this.put("httpcode", httpcode.code());
        this.put("httperror", httpcode.error());
    }

    /**
     * 带参数构造函数
     *
     * @param rs         业务处理成功
     * @param message    业务提示消息
     * @param resultcode 响应状态码
     */
    public Response(boolean rs, String message, Resultcode resultcode) {
        if (resultcode == null) resultcode = rs ? Resultcode.RESPONSE_SUCCESS : Resultcode.FAIL;
        Httpcode httpcode = rs ? Httpcode.SUCCESS : Httpcode.RESPONSE_FAIL;
        this.rs = rs;
        this.message = message;
        this.resultcode = resultcode.getCode();
        this.resulterror = resultcode.getError();
        this.httpcode = httpcode.getCode();
        this.httperror = httpcode.getError();
        this.put("rs", rs);
        this.put("message", message);
        this.put("resultcode", resultcode.code());
        this.put("resulterror", resultcode.error());
        this.put("httpcode", httpcode.code());
        this.put("httperror", httpcode.error());
    }

    /**
     * 业务处理是否成功
     *
     * @return
     */
    public boolean rs() {
        return rs;
    }

    /**
     * 返回成功响应数据
     *
     * @param message 业务提示消息
     * @return
     */
    public static Response success(String message) {
        return new Response(true, message);
    }

    /**
     * 返回统一响应错误数据
     *
     * @param message 业务提示消息
     * @return
     */
    public static Response fail() {
        return fail("fail", new Data[]{});
    }

    /**
     * 返回统一响应错误数据
     *
     * @param message 业务提示消息
     * @return
     */
    public static Response fail(String message) {
        return fail(message, new Data[]{});
    }

    /**
     * 返回统一响应错误数据
     *
     * @param message 业务提示消息
     * @param type    错误类型
     * @return
     */
    public static Response fail(String message, String type) {
        return fail(message, type, new Data[]{});
    }

    /**
     * 返回统一响应错误数据
     *
     * @param message 业务提示消息
     * @param datas   附加数据
     * @return
     */
    public static Response fail(String message, Data... datas) {
        return fail(message, null, datas);
    }

    /**
     * 返回统一响应错误数据
     *
     * @param message 业务提示消息
     * @param type    错误类型
     * @param datas   附加数据
     * @return
     */
    public static Response fail(String message, String type, Data... datas) {

        String lowerMessage = message.toLowerCase();
        Response data = fail(lowerMessage.contains("java") || lowerMessage.contains("sql") ? "十分抱歉~系统迷路了" : message, Resultcode.FAIL);
        if (type != null && !"".equals(type)) data.put("type", type);
        for (Data item : datas) {
            data.put(item.param, item.data);
        }
        return data;
    }

    /**
     * 返回响应错误数据
     *
     * @param message  业务提示消息
     * @param httpcode 响应码
     * @return
     */
    public static Response fail(String message, Httpcode httpcode) {
        return new Response(false, message, httpcode);
    }

    /**
     * 返回响应错误数据
     *
     * @param message  业务提示消息
     * @param httpcode 响应码
     * @param param    参数名
     * @param value    参数值
     * @return
     */
    public static Response fail(String message, Httpcode httpcode, String param, Object value) {
        return fail(message, httpcode).add(param, value);
    }

    /**
     * 返回响应错误数据
     *
     * @param message    业务提示消息
     * @param resultcode 响应码
     * @return
     */
    public static Response fail(String message, Resultcode resultcode) {
        return new Response(false, message, resultcode);
    }

    /**
     * 返回响应错误数据
     *
     * @param message    业务提示消息
     * @param resultcode 响应码
     * @param param      参数名
     * @param value      参数值
     * @return
     */
    public static Response fail(String message, Resultcode resultcode, String param, Object value) {
        return fail(message, resultcode).add(param, value);
    }

    /**
     * 参数对象
     *
     * @author Sinlon
     */
    public static class Data {
        /**
         * 参数名
         */
        private String param;
        /**
         * 参数值
         */
        private Object data;

        /**
         * 构造方法
         *
         * @param param 参数名
         * @param data  参数值
         */
        public Data(String param, Object data) {
            super();
            this.param = param;
            this.data = data;
        }

        /**
         * 获取参数名
         *
         * @return
         */
        public String getParam() {
            return param;
        }

        /**
         * 设置参数名
         *
         * @param param 参数名
         */
        public void setParam(String param) {
            this.param = param;
        }

        /**
         * 获取参数值
         *
         * @return
         */
        public Object getData() {
            return data;
        }

        /**
         * 设置参数值
         *
         * @param data 参数值
         */
        public void setData(Object data) {
            this.data = data;
        }

        /**
         * 构造新参数对象
         *
         * @param param 参数名
         * @param data  参数值
         * @return
         */
        public static Data build(String param, Object data) {
            return new Data(param, data);
        }

        /**
         * 创建新参数对象
         *
         * @param param 参数名
         * @param value 参数值
         * @return
         */
        public static Data created(String param, Object value) {
            return build(param, value);
        }
    }

    /**
     * 添加响应数据并返回对象
     *
     * @param param 参数名
     * @param value 参数值
     * @return
     */
    public Response add(String param, Object value) {
        this.put(param, value);
        return this;
    }

    /**
     * 返回成功响应数据和额外数据
     *
     * @param message 业务提示消息
     * @param param   参数名
     * @param value   参数值
     * @return
     */
    public static Response success(String message, String param, Object value) {
        return success(message).add(param, value);
    }

    /**
     * 返回获取数据成功响应数据
     *
     * @param data 信息对象
     * @return
     */
    public static Response dataSuccess(Object data) {
        return success("获取成功", "data", data);
    }
}

/**
 * 定义HTTP状态码
 *
 * @author Sinlon
 */
enum Httpcode {
    /**
     * 请求成功
     */
    SUCCESS(200, "请求响应成功"),
    /**
     * 请求损坏
     */
    REQUEST_BAD(400, "请求损坏"),
    /**
     * 请求未授权
     */
    REQUEST_NOT_AUTH(401, "请求未授权"),
    /**
     * 请求拒绝
     */
    REQUEST_FORBIDDEN(403, "请求拒绝"),
    /**
     * 请求未找到
     */
    REQUEST_NOT_FOUND(404, "请求未找到"),
    /**
     * 请求不允许
     */
    REQUEST_NOT_ALLOW(405, "请求不允许"),
    /**
     * 服务器响应错误
     */
    RESPONSE_FAIL(500, "服务器响应错误");

    // 成员变量
    /**
     * 响应码
     */
    private int code;
    /**
     * 响应消息
     */
    private String error;

    /**
     * 构造方法
     *
     * @param code  响应码
     * @param error 响应消息
     */
    Httpcode(Integer code, String error) {
        this.code = code;
        this.error = error;
    }

    /**
     * 根据code获取Enum
     *
     * @param code 响应码
     * @return
     */
    public static Httpcode get(int code) {
        Httpcode[] enums = values();
        for (Httpcode item : enums) {
            if (item.code() == code) {
                return item;
            }
        }
        return RESPONSE_FAIL;
    }

    // getter和setter

    /**
     * 获取响应码
     *
     * @return
     */
    public int getCode() {
        return code;
    }

    /**
     * 设置响应码
     *
     * @param code 响应码
     */
    public void setCode(int code) {
        this.code = code;
    }

    /**
     * 获取响应消息
     *
     * @return
     */
    public String getError() {
        return error;
    }

    /**
     * 设置响应消息
     *
     * @param error 响应消息
     */
    public void setError(String error) {
        this.error = error;
    }

    /**
     * 获取响应码
     *
     * @return
     */
    public int code() {
        return code;
    }

    /**
     * 设置响应码
     *
     * @param code 响应码
     */
    public void code(int code) {
        this.code = code;
    }

    /**
     * 获取响应消息
     *
     * @return
     */
    public String error() {
        return error;
    }

    /**
     * 设置响应消息
     *
     * @param error 响应消息
     */
    public void error(String error) {
        this.error = error;
    }
}

/**
 * 定义结果状态码
 *
 * @author Sinlon
 */
enum Resultcode {
    /**
     * 响应成功
     */
    RESPONSE_SUCCESS(2000, "响应成功"),
    /**
     * 请求错误
     */
    REQURST_FAIL(4000, "请求错误"),
    /**
     * 参数已存在
     */
    PARAM_EXISTS(4100, "参数已存在"),
    /**
     * 参数为空
     */
    PARAM_IS_NULL(4101, "参数为空"),
    /**
     * 参数类型错误
     */
    PARAM_TYPE_FAIL(4102, "参数类型错误"),
    /**
     * 参数输入错误
     */
    PARAM_INPUT_FAIL(4103, "参数输入错误"),
    /**
     * 数据为空
     */
    DATA_IS_NULL(5101, "数据为空"),
    /**
     * 数据状态错误
     */
    DATA_TYPE_FAIL(5102, "数据状态错误"),
    /**
     * 数据状态错误
     */
    DATA_STATUS_FAIL(5103, "数据状态错误"),
    /**
     * 服务器数据响应错误
     */
    FAIL(5200, "服务器数据响应错误"),
    /**
     * 列表获取失败
     */
    DATA_LIST_FAIL(5201, "列表获取失败"),
    /**
     * 数据获取失败
     */
    DATA_LOAD_FAIL(5202, "数据获取失败"),
    /**
     * 数据保存失败
     */
    DATA_SAVE_FAIL(5203, "数据保存失败"),
    /**
     * 数据更新失败
     */
    DATA_UPDATE_FAIL(5204, "数据更新失败"),
    /**
     * 数据状态切换失败
     */
    DATA_TURN_FAIL(5205, "数据状态切换失败"),
    /**
     * 数据删除失败
     */
    DATA_DELETE_FAIL(5206, "数据删除失败"),
    /**
     * 导入失败
     */
    IMPORT_FAIL(5207, "导入失败"),
    /**
     * 上传失败
     */
    UPLOAD_FAIL(5208, "上传失败"),
    /**
     * 登录失败
     */
    SIGNIN_FAIL(5209, "登录失败"),
    /**
     * 注销失败
     */
    SIGNOUT_FAIL(5210, "注销失败"),
    /**
     * 注册失败
     */
    SIGNUP_FAIL(5211, "注册失败"),
    /**
     * 校验失败
     */
    CHECK_FAIL(5212, "校验失败"),
    /**
     * 处理完成
     */
    COMPLATE(9999, "处理完成");

    // 成员变量
    /**
     * 结果码
     */
    private int code;
    /**
     * 结果描述
     */
    private String error;

    /**
     * 构造方法
     *
     * @param code  结果码
     * @param error 结果描述
     * @return
     */
    Resultcode(Integer code, String error) {
        this.code = code;
        this.error = error;
    }

    /**
     * 根据code获取Enum
     *
     * @param code
     * @return
     */
    public static Resultcode get(int code) {
        Resultcode[] enums = values();
        for (Resultcode item : enums) {
            if (item.code() == code) {
                return item;
            }
        }
        return FAIL;
    }

    // getter和setter

    /**
     * 获取结果码
     *
     * @return
     */
    public int getCode() {
        return code;
    }

    /**
     * 设置结果码
     *
     * @param code 结果码
     */
    public void setCode(int code) {
        this.code = code;
    }

    /**
     * 获取结果描述
     *
     * @return
     */
    public String getError() {
        return error;
    }

    /**
     * 设置结果描述
     *
     * @param error 结果描述
     */
    public void setError(String error) {
        this.error = error;
    }

    /**
     * 获取结果码
     *
     * @return
     */
    public int code() {
        return code;
    }

    /**
     * 设置结果码
     *
     * @param code 结果码
     */
    public void code(int code) {
        this.code = code;
    }

    /**
     * 获取结果描述
     *
     * @return
     */
    public String error() {
        return error;
    }

    /**
     * 设置结果描述
     *
     * @param error 结果描述
     */
    public void error(String error) {
        this.error = error;
    }
}
